package accx

import (
	"accx/appFramework/m_config"
	"accx/utils/httpClient"
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/cihub/seelog"
	"net/http"
	"strconv"
)

type SmfRegistInfo struct {
	NfInstanceID      string         `json:"nfInstanceId"`
	NfInstanceName    string         `json:"nfInstanceName"`
	NfType            string         `json:"nfType"`
	NfStatus          string         `json:"nfStatus"`
	HeartBeatTimer    int            `json:"heartBeatTimer"`
	PlmnList          []PlmnID       `json:"plmnList"`
	PerPlmnSnssaiList []PlmnSnssai   `json:"perPlmnSnssaiList"`
	Ipv4Addresses     []string       `json:"ipv4Addresses"`
	Capacity          int            `json:"capacity"`
	Load              int            `json:"load"`
	Priority          int            `json:"priority"`
	SmfInfo           SmfInfo        `json:"smfInfo"`
	NfServices        []SmfNfService `json:"nfServices"`
	StaticIPSegment   []string       `json:"staticIpSegment"`
}
type PlmnID struct {
	Mcc string `json:"mcc"`
	Mnc string `json:"mnc"`
}
type SNssai struct {
	Sst int    `json:"sst"`
	Sd  string `json:"sd"`
}
type PlmnSnssai struct {
	PlmnID     PlmnID   `json:"plmnId"`
	SNssaiList []SNssai `json:"sNssaiList"`
}
type DnnSmfInfo struct {
	Dnn string `json:"dnn"`
}
type SNssaiSmfInfo struct {
	SNssai         SNssai       `json:"sNssai"`
	DnnSmfInfoList []DnnSmfInfo `json:"dnnSmfInfoList"`
}
type SmfInfo struct {
	SNssaiSmfInfoList []SNssaiSmfInfo `json:"sNssaiSmfInfoList"`
	PgwFqdn           string          `json:"pgwFqdn"`
}
type Versions struct {
	APIVersionInURI string `json:"apiVersionInUri"`
	APIFullVersion  string `json:"apiFullVersion"`
}
type IPEndPoints struct {
	Ipv4Address string `json:"ipv4Address"`
	Port        int    `json:"port"`
}
type SmfNfService struct {
	ServiceInstanceID string        `json:"serviceInstanceId"`
	ServiceName       string        `json:"serviceName"`
	Versions          []Versions    `json:"versions"`
	Scheme            string        `json:"scheme"`
	NfServiceStatus   string        `json:"nfServiceStatus"`
	IPEndPoints       []IPEndPoints `json:"ipEndPoints"`
}
type SmfUpadteInfos struct {
	Value []SmfUpadteInfo
}
type SmfUpadteInfo struct {
	Op    string   `json:"op"`
	Path  string   `json:"path"`
	Value []string `json:"value"`
}
type AmfRegistInfo struct {
	AllowedNfTypes    []string       `json:"allowedNfTypes"`
	AmfInfo           AmfInfo        `json:"amfInfo"`
	Ipv4Addresses     []string       `json:"ipv4Addresses"`
	NfInstanceID      string         `json:"nfInstanceId"`
	NfInstanceName    string         `json:"nfInstanceName"`
	NfServices        []AmfNfService `json:"nfServices"`
	NfStatus          string         `json:"nfStatus"`
	NfType            string         `json:"nfType"`
	PerPlmnSnssaiList []PlmnSnssai   `json:"perPlmnSnssaiList"`
	PlmnList          []PlmnID       `json:"plmnList"`
}
type GuamiList struct {
	AmfID  string `json:"amfId"`
	PlmnID PlmnID `json:"plmnId"`
}
type AmfInfo struct {
	AmfRegionID string      `json:"amfRegionId"`
	AmfSetID    string      `json:"amfSetId"`
	GuamiList   []GuamiList `json:"guamiList"`
}
type DefaultNotificationSubscriptions struct {
	CallbackURI      string `json:"callbackUri"`
	N1MessageClass   string `json:"n1MessageClass"`
	NotificationType string `json:"notificationType"`
}
type AmfNfService struct {
	DefaultNotificationSubscriptions []DefaultNotificationSubscriptions `json:"defaultNotificationSubscriptions"`
	IPEndPoints                      []IPEndPoints                      `json:"ipEndPoints"`
	NfServiceStatus                  string                             `json:"nfServiceStatus"`
	Scheme                           string                             `json:"scheme"`
	ServiceInstanceID                string                             `json:"serviceInstanceId"`
	ServiceName                      string                             `json:"serviceName"`
	Versions                         []Versions                         `json:"versions"`
}

func (smfRegistInfo *SmfRegistInfo) LocalSmfRegist() {
	myaccx := m_config.MyAccxData
	smfinstanceid := myaccx.NfInstanceIds.Smf
	smfRegistInfo.NfInstanceID = smfinstanceid
	smfRegistInfo.NfInstanceName = "smf01"
	smfRegistInfo.NfType = "SMF"
	smfRegistInfo.NfType = "REGISTERED"
	smfRegistInfo.HeartBeatTimer = 15
	var plmn PlmnID
	plmn.Mcc = myaccx.PlmnList[0].Mcc
	plmn.Mnc = myaccx.PlmnList[0].Mnc
	smfRegistInfo.PlmnList = append(smfRegistInfo.PlmnList, plmn)
	var plmnsnssai PlmnSnssai
	var snssai SNssai
	snssai.Sd = myaccx.NssaiList[0].Sd
	snssai.Sst = myaccx.NssaiList[0].Sst
	plmnsnssai.PlmnID = plmn
	plmnsnssai.SNssaiList = append(plmnsnssai.SNssaiList, snssai)
	smfRegistInfo.PerPlmnSnssaiList = append(smfRegistInfo.PerPlmnSnssaiList, plmnsnssai)
	smfRegistInfo.Ipv4Addresses = append(smfRegistInfo.Ipv4Addresses, myaccx.ServiceIp)
	smfRegistInfo.Capacity = 1000
	smfRegistInfo.Load = 10
	smfRegistInfo.Priority = 10
	var smfinfo SmfInfo
	var sNssaiSmfInfo SNssaiSmfInfo
	var dnnSmfInfo DnnSmfInfo
	sNssaiSmfInfo.SNssai = snssai
	for _, v := range myaccx.DnnList {
		dnnSmfInfo.Dnn = v
		sNssaiSmfInfo.DnnSmfInfoList = append(sNssaiSmfInfo.DnnSmfInfoList, dnnSmfInfo)
	}
	smfinfo.SNssaiSmfInfoList = append(smfinfo.SNssaiSmfInfoList, sNssaiSmfInfo)
	smfinfo.PgwFqdn = "pgwc.net.com"
	smfRegistInfo.SmfInfo = smfinfo
	var nfservice SmfNfService
	nfservice.ServiceName = "nsmf-pdusession"
	nfservice.ServiceInstanceID = "1"
	var version Versions
	version.APIVersionInURI = "V1"
	version.APIFullVersion = "v16.0.0"
	nfservice.Versions = append(nfservice.Versions, version)
	nfservice.Scheme = "http"
	nfservice.NfServiceStatus = "REGISTERED"
	var ipendpoint IPEndPoints
	ipendpoint.Ipv4Address = myaccx.ServiceIp
	ipendpoint.Port = 8200
	nfservice.IPEndPoints = append(nfservice.IPEndPoints, ipendpoint)
	smfRegistInfo.NfServices = append(smfRegistInfo.NfServices, nfservice)
	staticip := myaccx.StaticIpSegment[0]
	smfRegistInfo.StaticIPSegment = append(smfRegistInfo.StaticIPSegment, staticip)
	cli := httpClient.NewHttp2Client()
	marshalData, _ := json.Marshal(smfRegistInfo)
	req, err := http.NewRequest("PUT", "http://"+myaccx.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+smfinstanceid, bytes.NewReader(marshalData))
	if err != nil {
		seelog.Error("Smf regist request is err:", err)
		return
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Smf regist DoRequest is err:", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Smf regist resp is err")
	}
}
func LocalSmfUpdate() {
	var smfupdate SmfUpadteInfo
	smfupdate.Op = "replace"
	smfupdate.Path = "/staticIpSegment"
	myaccx := m_config.MyAccxData
	smfinstanceid := myaccx.NfInstanceIds.Smf
	smfupdate.Value = append(smfupdate.Value, myaccx.StaticIpSegment...)
	cli := httpClient.NewHttp2Client()
	marshalData, _ := json.Marshal(smfupdate)
	req, err := http.NewRequest("PATCH", "http://"+myaccx.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+smfinstanceid, bytes.NewReader(marshalData))
	if err != nil {
		seelog.Error("Smf regist request is err:", err)
		return
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Smf regist DoRequest is err:", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Amf UserDeregist resp is err")
	}
}
func LocalSmfDeRegist() {

}
func PeerSmfRegist(group string, node string) bool {
	var accx m_config.Accx
	for _, v := range m_config.AccxAndAllaccxData.Accx {
		if group == v.Group && node == v.Node {
			accx = v
		}
	}
	smfinstanceid := accx.NfInstanceIds.Smf
	var smfRegistInfo SmfRegistInfo
	smfRegistInfo.NfInstanceID = smfinstanceid
	smfRegistInfo.NfInstanceName = "smf01"
	smfRegistInfo.NfType = "SMF"
	smfRegistInfo.NfType = "REGISTERED"
	smfRegistInfo.HeartBeatTimer = 15
	var plmn PlmnID
	plmn.Mcc = accx.PlmnList[0].Mcc
	plmn.Mnc = accx.PlmnList[0].Mnc
	smfRegistInfo.PlmnList = append(smfRegistInfo.PlmnList, plmn)
	var plmnsnssai PlmnSnssai
	var snssai SNssai
	snssai.Sd = accx.NssaiList[0].Sd
	snssai.Sst = accx.NssaiList[0].Sst
	plmnsnssai.PlmnID = plmn
	plmnsnssai.SNssaiList = append(plmnsnssai.SNssaiList, snssai)
	smfRegistInfo.PerPlmnSnssaiList = append(smfRegistInfo.PerPlmnSnssaiList, plmnsnssai)
	smfRegistInfo.Ipv4Addresses = append(smfRegistInfo.Ipv4Addresses, accx.ServiceIp)
	smfRegistInfo.Capacity = 1000
	smfRegistInfo.Load = 10
	smfRegistInfo.Priority = 10
	var smfinfo SmfInfo
	var sNssaiSmfInfo SNssaiSmfInfo
	var dnnSmfInfo DnnSmfInfo
	sNssaiSmfInfo.SNssai = snssai
	for _, v := range accx.DnnList {
		dnnSmfInfo.Dnn = v
		sNssaiSmfInfo.DnnSmfInfoList = append(sNssaiSmfInfo.DnnSmfInfoList, dnnSmfInfo)
	}
	smfinfo.SNssaiSmfInfoList = append(smfinfo.SNssaiSmfInfoList, sNssaiSmfInfo)
	smfinfo.PgwFqdn = "pgwc.net.com"
	smfRegistInfo.SmfInfo = smfinfo
	var nfservice SmfNfService
	nfservice.ServiceName = "nsmf-pdusession"
	nfservice.ServiceInstanceID = "1"
	var version Versions
	version.APIVersionInURI = "V1"
	version.APIFullVersion = "v16.0.0"
	nfservice.Versions = append(nfservice.Versions, version)
	nfservice.Scheme = "http"
	nfservice.NfServiceStatus = "REGISTERED"
	var ipendpoint IPEndPoints
	ipendpoint.Ipv4Address = accx.ServiceIp
	ipendpoint.Port = 8200
	nfservice.IPEndPoints = append(nfservice.IPEndPoints, ipendpoint)
	smfRegistInfo.NfServices = append(smfRegistInfo.NfServices, nfservice)
	for _, v := range accx.StaticIpSegment {
		smfRegistInfo.StaticIPSegment = append(smfRegistInfo.StaticIPSegment, v)
	}
	cli := httpClient.NewHttp2Client()
	marshalData, _ := json.Marshal(smfRegistInfo)
	req, err := http.NewRequest("PUT", "http://"+m_config.MyAccxData.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+smfinstanceid, bytes.NewReader(marshalData))
	if err != nil {
		seelog.Error("Smf regist request is err:", err)
		return false
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Smf regist DoRequest is err:", err)
		return false
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Amf UserDeregist resp is err")
	}
	return true
}
func PeerSmfUpdate(staticIpSegment []string, nfinstanceid string) bool {
	var smfupdate SmfUpadteInfo
	smfupdate.Op = "replace"
	smfupdate.Path = "/staticIpSegment"
	myaccx := m_config.MyAccxData
	smfupdate.Value = staticIpSegment
	cli := httpClient.NewHttp2Client()
	marshalData, _ := json.Marshal(smfupdate)
	req, err := http.NewRequest("PATCH", "http://"+myaccx.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+nfinstanceid, bytes.NewReader(marshalData))
	if err != nil {
		seelog.Error("Smf regist request is err:", err)
		return false
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Smf regist DoRequest is err:", err)
		return false
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Amf UserDeregist resp is err")
	}
	return true
}
func PeerNfDeRegist(nfinstanceid string) {
	myaccx := m_config.MyAccxData
	cli := httpClient.NewHttp2Client()
	req, err := http.NewRequest("DELETE", "http://"+myaccx.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+nfinstanceid, nil)
	if err != nil {
		seelog.Error("Smf regist request is err:", err)
		return
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Smf regist DoRequest is err:", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Amf UserDeregist resp is err")
	}
}
func PeerAmfRegist(group string, node string) bool {
	var accx m_config.Accx
	for _, v := range m_config.AccxAndAllaccxData.Accx {
		if group == v.Group && node == v.Node {
			accx = v
		}
	}
	amfinstanceid := accx.NfInstanceIds.Amf
	var amfRegistInfo AmfRegistInfo
	amfRegistInfo.NfInstanceID = amfinstanceid
	amfRegistInfo.AllowedNfTypes = append(amfRegistInfo.AllowedNfTypes, "AMF", "UDM", "SMF", "UPF", "PCF", "AUSF")
	var amfinfo AmfInfo
	var sNssaiSmfInfo SNssaiSmfInfo
	var dnnSmfInfo DnnSmfInfo
	for _, v := range accx.DnnList {
		dnnSmfInfo.Dnn = v
		sNssaiSmfInfo.DnnSmfInfoList = append(sNssaiSmfInfo.DnnSmfInfoList, dnnSmfInfo)
	}
	var guamilist GuamiList
	regionId, _ := strconv.Atoi(accx.Guami.AmfRegionId)
	setid, _ := strconv.Atoi(accx.Guami.AmfSetid)
	pointer, _ := strconv.Atoi(accx.Guami.AmfPointer)
	// 将各部分的值转换为二进制字符串并进行拼接
	binRegionID := fmt.Sprintf("%08b", regionId)
	binSetID := fmt.Sprintf("%010b", setid)
	binPointer := fmt.Sprintf("%06b", pointer)
	combinedBin := binRegionID + binSetID + binPointer
	amfIDDecimal, _ := strconv.ParseInt(combinedBin, 2, 64)
	amfID := fmt.Sprintf("%06X", amfIDDecimal)
	guamilist.AmfID = amfID
	var plmn PlmnID
	plmn.Mcc = accx.PlmnList[0].Mcc
	plmn.Mnc = accx.PlmnList[0].Mnc
	guamilist.PlmnID = plmn
	amfinfo.GuamiList = append(amfinfo.GuamiList, guamilist)
	amfinfo.AmfRegionID = accx.Guami.AmfRegionId
	amfinfo.AmfSetID = accx.Guami.AmfSetid
	amfRegistInfo.AmfInfo = amfinfo
	amfRegistInfo.Ipv4Addresses = append(amfRegistInfo.Ipv4Addresses, accx.ServiceIp)
	amfRegistInfo.NfInstanceName = "amf01"
	var amfservice AmfNfService
	var defaultNotificationSubscriptions DefaultNotificationSubscriptions
	defaultNotificationSubscriptions.NotificationType = "N1_MESSAGES"
	defaultNotificationSubscriptions.CallbackURI = "http://" + accx.ServiceIp + ":8100/namf-comm/v1/n1Notify/ue-contexts/ueContextId/gmm-messages/subscriptions"
	defaultNotificationSubscriptions.N1MessageClass = "5GMM"
	amfservice.DefaultNotificationSubscriptions = append(amfservice.DefaultNotificationSubscriptions, defaultNotificationSubscriptions)
	var ipendpoint IPEndPoints
	ipendpoint.Ipv4Address = accx.ServiceIp
	ipendpoint.Port = 8100
	amfservice.IPEndPoints = append(amfservice.IPEndPoints, ipendpoint)
	amfservice.NfServiceStatus = "REGISTERED"
	amfservice.Scheme = "http"
	amfservice.ServiceInstanceID = "amf01.namf-comm"
	amfservice.ServiceName = "namf-comm"
	var version Versions
	version.APIVersionInURI = "V1"
	version.APIFullVersion = "1.R16.0.0"
	amfservice.Versions = append(amfservice.Versions, version)
	amfRegistInfo.NfServices = append(amfRegistInfo.NfServices, amfservice)
	amfRegistInfo.NfType = "AMF"
	amfRegistInfo.NfStatus = "REGISTERED"
	amfRegistInfo.PlmnList = append(amfRegistInfo.PlmnList, plmn)
	var plmnsnssai PlmnSnssai
	var snssai SNssai
	snssai.Sd = accx.NssaiList[0].Sd
	snssai.Sst = accx.NssaiList[0].Sst
	plmnsnssai.PlmnID = plmn
	plmnsnssai.SNssaiList = append(plmnsnssai.SNssaiList, snssai)
	amfRegistInfo.PerPlmnSnssaiList = append(amfRegistInfo.PerPlmnSnssaiList, plmnsnssai)
	cli := httpClient.NewHttp2Client()
	marshalData, _ := json.Marshal(amfRegistInfo)
	req, err := http.NewRequest("PUT", "http://"+m_config.MyAccxData.ServiceIp+":8600"+"/nnrf-nfm/v1/nf-instances/"+amfinstanceid, bytes.NewReader(marshalData))
	if err != nil {
		seelog.Error("Amf regist request is err:", err)
		return false
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("Amf regist DoRequest is err:", err)
		return false
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusCreated {
		seelog.Error("Amf regist resp is err")
	}
	return true
}
